<template>
    <el-form :model="regoinForm">
        <el-form-item v-if="!isDetail" style="margin-bottom: 0" label=" " :label-width="formLabelWidth">
            <el-checkbox-group
                @change="
                    handleAllElection($event);
                    handleChange();
                "
                v-model="regoinForm.all"
            >
                <el-checkbox :indeterminate="indeterminateAllElection" label="全选" name="type"></el-checkbox>
            </el-checkbox-group>
        </el-form-item>
        <el-form-item style="margin-bottom: 0" prop="floors_range" label=" " :label-width="formLabelWidth">
            <el-table
                :show-header="false"
                :highlight-current-row="false"
                :data="tableAuthData"
                :span-method="objectSpanMethod"
                style="width: 100%"
                class="user-auth-list"
                border
            >
                <el-table-column align="left" width="120">
                    <template v-slot="{row}">
                        <template v-if="isDetail && regoinForm.selectParentModules.length > 0">
                            {{ row.parent.name }}
                        </template>
                        <template v-else>
                            <el-checkbox-group
                                @change="
                                    handleParentChange(row.parent.id, $event);
                                    handleChange();
                                "
                                v-model="regoinForm.selectParentModules"
                            >
                                <el-checkbox :label="row.parent.id" :indeterminate="indeterminateParent[row.parent.id]"
                                    >{{ row.parent.name }}
                                </el-checkbox>
                            </el-checkbox-group>
                        </template>
                    </template>
                </el-table-column>
                <el-table-column align="left">
                    <template v-slot="{row}">
                        <template v-if="isDetail">
                            <template v-if="row.child.hidden">
                                <el-row>
                                    <el-col
                                        :xs="24"
                                        :sm="24"
                                        :md="12"
                                        :lg="12"
                                        :xl="8"
                                        v-for="functionItem in row.functionGroup"
                                        :key="functionItem.id"
                                    >
                                        {{ functionItem.name }}
                                    </el-col>
                                </el-row>
                            </template>
                            <template v-else>
                                {{ row.child.name }}
                            </template>
                        </template>
                        <template v-else>
                            <template v-if="row.child.hidden">
                                <el-checkbox-group
                                    @change="
                                        handleFunctionChange(row.child.id, $event);
                                        handleChange();
                                    "
                                    v-model="regoinForm.selectedFunctionMap[row.child.id]"
                                >
                                    <el-row>
                                        <el-col
                                            :xs="24"
                                            :sm="24"
                                            :md="12"
                                            :lg="12"
                                            :xl="8"
                                            v-for="functionItem in row.functionGroup"
                                            :key="functionItem.id"
                                        >
                                            <el-checkbox
                                                @change="handleClickFunctionItem(row.child.id, functionItem)"
                                                :label="functionItem.id"
                                                :indeterminate="false"
                                                >{{ functionItem.name }}</el-checkbox
                                            >
                                        </el-col>
                                    </el-row>
                                </el-checkbox-group>
                            </template>
                            <template>
                                <el-checkbox-group
                                    v-show="!row.child.hidden"
                                    @change="
                                        handleChildChange(row.child.id, $event);
                                        handleChange();
                                    "
                                    v-model="regoinForm.selectChildModuleMap[row.parent.id]"
                                >
                                    <el-checkbox
                                        :label="row.child.id"
                                        :indeterminate="indeterminateChild[row.child.id]"
                                    >
                                        {{ row.child.name }}</el-checkbox
                                    >
                                </el-checkbox-group>
                            </template>
                        </template>
                    </template>
                </el-table-column>
                <el-table-column align="left">
                    <template v-slot="{row}">
                        <template v-if="isDetail">
                            <el-row>
                                <el-col
                                    :xs="24"
                                    :sm="24"
                                    :md="12"
                                    :lg="12"
                                    :xl="8"
                                    v-for="functionItem in row.functionGroup"
                                    :key="functionItem.id"
                                    >{{ functionItem.name }}
                                </el-col>
                            </el-row>
                        </template>
                        <template v-else>
                            <el-checkbox-group
                                v-if="!row.child.hidden"
                                @change="
                                    handleFunctionChange(row.child.id, $event);
                                    handleChange();
                                "
                                v-model="regoinForm.selectedFunctionMap[row.child.id]"
                            >
                                <el-row>
                                    <el-col
                                        :xs="24"
                                        :sm="24"
                                        :md="12"
                                        :lg="12"
                                        :xl="8"
                                        v-for="functionItem in row.functionGroup"
                                        :key="functionItem.id"
                                    >
                                        <el-checkbox
                                            @change="handleClickFunctionItem(row.child.id, functionItem)"
                                            :label="functionItem.id"
                                            :indeterminate="false"
                                            >{{ functionItem.name }}</el-checkbox
                                        >
                                    </el-col>
                                </el-row>
                            </el-checkbox-group>
                        </template>
                    </template>
                </el-table-column>
            </el-table>
        </el-form-item>
    </el-form>
</template>
<script>
export default {
    name: 'permission-check-group',
    props: {
        isDetail: {
            type: Boolean,
            default: false
        },
        formLabelWidth: {
            type: String,
            default: '120px'
        },
        value: {
            type: Array,
            default: () => []
        },
        modelPermission: {
            type: Object,
            default: () => ({
                childModules: [],
                functionMap: {},
                parentModules: [],
                selectedFunctions: [],
                selectedModules: []
            })
        }
    },
    data() {
        return {
            tableAuthData: [],
            regoinForm: {
                all: false,
                selectParentModules: [], // 选中的parent模块
                selectChildModuleMap: {}, // 选中child模块
                selectedFunctionMap: {} // 选中的功能列表；
            }, // 添加用户 form
            parentModules: [], // 全部的一级模块列表
            childModules: [], // 全部的二级模块列表；一级模块和二级模块通过parentId关联
            functionMap: {}, // key为所属二级模块的ID，value为二级模块下的功能列表
            selectedModules: [], // 选中的模块列表；
            selectedFunctions: [], // 选中的功能列表；
            indeterminateParent: {}, // parent半选中状态
            indeterminateChild: {}, // child半选中状态
            indeterminateAllElection: false // all election半选中状态
        };
    },
    watch: {
        modelPermission: {
            handler(val) {
                this.getInitialPermissions(val);
                // 初始化更新
                this.handleChange(true);
            },
            immediate: true
        }
    },
    methods: {
        // checkbox发生改变的时候 触发
        handleChange(initial) {
            const newItem = {
                parentModules: this.parentModules,
                childModules: this.childModules,
                functionMap: this.functionMap,
                ...this.regoinForm
            };
            const {childModules, functionMap, selectedFunctionMap, selectChildModuleMap} = newItem;
            const permissionIds = [];
            childModules.forEach(item => {
                const funcArr = functionMap[item.id];
                // 如果 不存在 function 模块
                // 当前 模块作为 function 模块进行判断
                if (!funcArr && selectChildModuleMap[item.parentId].indexOf(item.id) !== -1) {
                    permissionIds.push(item.id);
                }
            });
            for (let keys of Object.keys(selectedFunctionMap)) {
                permissionIds.push(...selectedFunctionMap[keys]);
            }

            // this.regoinForm.permissions_ids = permissionIds;
            this.$emit('input', permissionIds);
            // 初始化更新
            if (initial !== true) {
                this.$emit('change', permissionIds);
            }
        },
        // 初始化权限列表
        getInitialPermissions(result) {
            const {parentModules, childModules, functionMap, selectedModules, selectedFunctions} = result;
            /* S 生成权限列表数据 */
            const tableAuthData = [];
            const selectParentModules = []; // 选中的parent模块
            const selectChildModuleMap = {}; // 选中child模块
            const selectedFunctionMap = {}; // 选中的功能列表；
            const indeterminateParent = {}; // 半选中 选中的parent模块
            if (parentModules.length > 0) {
                for (let parentItem of parentModules) {
                    // 初始化child select
                    // selectChildModuleMap[parentItem.id] = [];
                    // 判断已经选择的模块中是否存在children模块
                    const currentChildren = selectedModules.filter(i => i.parentId === parentItem.id);
                    selectChildModuleMap[parentItem.id] = currentChildren.map(i => i.id);

                    // 根据childModule获取选择的parentId， 使用Set数据结构去重
                    selectParentModules.push(...[...new Set(currentChildren.map(i => i.parentId))]);

                    const childItems = childModules.filter(childItem => {
                        return childItem.parentId === parentItem.id;
                    });
                    // parent半选中状态
                    if (currentChildren.length > 0 && currentChildren.length < childItems.length) {
                        indeterminateParent[parentItem.id] = true;
                    }

                    // ！！！特殊情况，特殊处理。如果没有 child 只有 function
                    if (childItems.length === 0) {
                        const functionGroup = functionMap[parentItem.id] || [];

                        if (functionGroup.length > 0) {
                            // 生成一个citem
                            const citem = {
                                hidden: true, // 是否隐藏二级
                                id: functionGroup[0].moduleId,
                                name: 'hidden',
                                parentId: functionGroup[0].moduleId
                            };
                            childModules.push({...citem});
                            let newItem = {
                                isRowSpan: true,
                                rowNumber: 1,
                                isColSpan: true,
                                parent: parentItem,
                                child: citem,
                                functionGroup: functionGroup
                            };

                            // 初始化functions
                            // selectedFunctionMap[citem.id] = [];
                            const currentFunction = selectedFunctions
                                .filter(i => i.moduleId === citem.id)
                                .map(i => i.id);
                            selectedFunctionMap[citem.id] = currentFunction;

                            // 判断是否是查看详情 && 选中的 length > 0
                            if (!(this.isDetail && selectedFunctionMap[citem.id].length === 0)) {
                                if (currentFunction.length > 0) {
                                    selectParentModules.push(citem.parentId);
                                }
                                // 如果是查看详情
                                if (this.isDetail) {
                                    newItem.functionGroup = functionGroup.filter(item => {
                                        return selectedFunctionMap[citem.id].includes(item.id);
                                    });
                                }

                                tableAuthData.push(newItem);
                            }
                        }
                    } else {
                        let currentChildItems;
                        // 判断是否是查看详情
                        if (this.isDetail) {
                            currentChildItems = childItems.filter(item => {
                                return selectChildModuleMap[item.parentId].includes(item.id);
                            });
                        } else {
                            currentChildItems = childItems;
                        }
                        // 跨行合并number
                        const rowNumber = currentChildItems.length;

                        currentChildItems.forEach((citem, index) => {
                            const functionGroup = functionMap[citem.id] || [];
                            let newItem = {
                                isRowSpan: index === 0,
                                parent: parentItem,
                                child: citem,
                                functionGroup: functionGroup
                            };
                            if (newItem.isRowSpan) {
                                newItem.rowNumber = rowNumber;
                            }

                            // 初始化functions
                            // selectedFunctionMap[citem.id] = [];
                            const currentFunction = selectedFunctions
                                .filter(i => i.moduleId === citem.id)
                                .map(i => i.id);
                            selectedFunctionMap[citem.id] = currentFunction;

                            // 如果是查看详情
                            if (this.isDetail) {
                                newItem.functionGroup = functionGroup.filter(item => {
                                    return selectedFunctionMap[citem.id].includes(item.id);
                                });
                            }
                            tableAuthData.push(newItem);
                        });
                    }
                }
            }
            const {all, indeterminateAllElection, indeterminateChild} = this.caclAllElection({
                functionMap,
                selectedFunctionMap,
                childModules,
                selectChildModuleMap
            });

            if (this.isDetail) {
                // 1. 判断是否是`查看详情` 2. 根据是否选中parent过滤掉没有用到的权限项
                const filterTableAuthData = tableAuthData.filter(item => {
                    return (
                        // eslint-disable-next-line
                        (selectParentModules.includes(item.parent.id) &&
                            // eslint-disable-next-line
                            selectChildModuleMap[item.parent.id].includes(item.child.id)) ||
                        item.isColSpan
                    );
                });
                this.tableAuthData = filterTableAuthData;
            } else {
                this.tableAuthData = tableAuthData;
            }

            // 初始化用户授权表单
            this.regoinForm = {
                ...this.regoinForm,
                all,
                selectParentModules,
                selectChildModuleMap,
                selectedFunctionMap
            };
            this.indeterminateAllElection = indeterminateAllElection;
            this.indeterminateParent = indeterminateParent;
            this.indeterminateChild = indeterminateChild;

            // this.tableAuthData = tableAuthData;

            this.parentModules = parentModules;
            this.childModules = childModules;
            this.functionMap = functionMap;
            /* E 生成权限列表数据 */
            // });
        },
        // 计算是否全选 且半选中状态
        caclAllElection({functionMap, selectedFunctionMap, childModules, selectChildModuleMap}) {
            let indeterminateAllElection; // 是否半选中
            let all; // 全选按钮
            const countFunctionSelected = []; // 计算function模块选中
            const indeterminateChild = {};
            // childModules.forEach(item => {
            //     const funcArr = functionMap[item.id];
            //     // 如果 不存在 function 模块
            //     // 当前 模块作为 function 模块进行判断
            //     if (!funcArr) {
            //         // 已经选中childModule长度
            //         const selectedLength = selectChildModuleMap[item.parentId].length;
            //         // 所有的长度childModule长度
            //         const currentTotalLength = childModules.filter(i => i.parentId === item.parentId).length;
            //         // 没有选中的length
            //         const noSelectLength = currentTotalLength - selectedLength;
            //         for (let i = 0; i < selectedLength; i++) {
            //             countFunctionSelected.push(true);
            //         }

            //         for (let i = 0; i < noSelectLength; i++) {
            //             countFunctionSelected.push(false);
            //         }
            //     }
            // });
            for (const key of Object.keys(functionMap)) {
                if (Array.isArray(selectedFunctionMap[key]) && selectedFunctionMap[key].length > 0) {
                    countFunctionSelected.push(true);
                    // 选中的功能模块长度 小于 所有的功能模块长度
                    if (selectedFunctionMap[key].length < functionMap[key].length) {
                        indeterminateChild[key] = true;
                    }
                } else {
                    countFunctionSelected.push(false);
                }
            }
            const everyTrue = countFunctionSelected.every(i => i === true);
            const everyFalse = countFunctionSelected.every(i => i === false);
            if (everyTrue || everyFalse) {
                indeterminateAllElection = false;
            } else {
                indeterminateAllElection = true;
            }

            if (everyTrue) {
                all = true;
            } else {
                all = false;
            }
            countFunctionSelected.length = 0; // gc
            return {all, indeterminateAllElection, indeterminateChild};
        },
        // 全选
        handleAllElection(val) {
            const parentModules = [...this.parentModules];
            const childModules = [...this.childModules];
            const functionMap = {...this.functionMap};

            const selectParentModules = []; // 选中的parent模块
            const selectChildModuleMap = {}; // 选中child模块
            const selectedFunctionMap = {}; // 选中的功能列表；
            // 全选
            if (val === true) {
                selectParentModules.push(...parentModules.map(i => i.id));
                // 全选
                if (parentModules.length > 0) {
                    for (let parentItem of parentModules) {
                        // 判断已经选择的模块中是否存在children模块
                        const currentChildren = childModules
                            .filter(i => {
                                return i.parentId === parentItem.id;
                            })
                            .map(i => i.id);
                        selectChildModuleMap[parentItem.id] = currentChildren;

                        const childItems = childModules.filter(childItem => {
                            return childItem.parentId === parentItem.id;
                        });

                        childItems.forEach((citem, index) => {
                            if (functionMap[citem.id]) {
                                selectedFunctionMap[citem.id] = functionMap[citem.id].map(i => i.id);
                            } else {
                                selectedFunctionMap[citem.id] = [];
                            }
                        });
                    }
                }
            } else {
                // 取消全选
                for (const key of Object.keys(this.regoinForm.selectChildModuleMap)) {
                    selectChildModuleMap[key] = [];
                }
                for (const key of Object.keys(this.regoinForm.selectedFunctionMap)) {
                    selectedFunctionMap[key] = [];
                }
            }
            // 取消半选中状态
            this.indeterminateAllElection = false;
            this.indeterminateParent = {};
            this.indeterminateChild = {};

            // 初始化用户授权表单
            this.regoinForm = {
                ...this.regoinForm,
                selectParentModules,
                selectChildModuleMap,
                selectedFunctionMap
            };
        },
        // 改变parent模块时触发
        handleParentChange(parentId, changeValue) {
            // 1. 全选 / 取消 child
            // 2. 全选 / 取消 function
            const regoinForm = this.regoinForm; // form
            const childModules = this.childModules;
            const functionMap = this.functionMap;
            const selectChildModuleMap = {...regoinForm.selectChildModuleMap};
            const selectedFunctionMap = {...regoinForm.selectedFunctionMap};
            const indeterminateParent = {...this.indeterminateParent}; // 选中 / 半选中
            const indeterminateChild = {...this.indeterminateChild}; // 选中 / 半选中

            selectChildModuleMap[parentId] = [];
            const children = childModules.forEach(citem => {
                indeterminateChild[citem.id] = false;
                if (citem.parentId === parentId) {
                    if (changeValue.includes(parentId)) {
                        selectChildModuleMap[parentId].push(citem.id);
                        // 防止只有 二级 没有三级操作
                        if (functionMap[citem.id]) {
                            selectedFunctionMap[citem.id] = functionMap[citem.id].map(i => i.id);
                        } else {
                            selectedFunctionMap[citem.id] = [];
                        }
                    } else {
                        selectedFunctionMap[citem.id] = [];
                    }
                }
            });
            // 取消child的半选状态
            this.indeterminateChild = indeterminateChild;

            indeterminateParent[parentId] = false;
            this.indeterminateParent = indeterminateParent;
            const {all, indeterminateAllElection} = this.caclAllElection({
                functionMap,
                selectedFunctionMap,
                childModules,
                selectChildModuleMap
            });
            this.indeterminateAllElection = indeterminateAllElection;
            this.regoinForm = {
                ...regoinForm,
                all,
                selectChildModuleMap,
                selectedFunctionMap
            };
        },
        // 选择children模块的时候触发
        handleChildChange(childId, changeValue) {
            // 1. 全选 childId对应的 功能
            // 2. 判断是否存在parentId选中，如果没有则添加
            // 3. 判断parentId是否是半选中状态
            const regoinForm = this.regoinForm; // form
            const childModules = this.childModules;
            const functionMap = this.functionMap;
            const indeterminateParent = {...this.indeterminateParent}; // 选中 / 半选中
            const indeterminateChild = {...this.indeterminateChild}; // 选中 / 半选中

            let selectParentModules = [...regoinForm.selectParentModules];
            const selectedFunctionMap = {...regoinForm.selectedFunctionMap};
            const selectChildModuleMap = {...regoinForm.selectChildModuleMap};
            /* S 对functions操作 */
            if (changeValue.includes(childId)) {
                // 如果当前没有选中

                // 防止只有 二级 没有三级操作
                if (functionMap[childId]) {
                    selectedFunctionMap[childId] = functionMap[childId].map(i => i.id);
                } else {
                    selectedFunctionMap[childId] = [];
                }
            } else {
                // 如果当前选中
                selectedFunctionMap[childId] = [];
            }
            /* E 对functions操作 */

            // 当前选中的children项
            const childItem = childModules.find(item => item.id === childId);

            // 对parent是否选中进行操作
            if (changeValue.length > 0 && !selectParentModules.includes(childItem.parentId)) {
                selectParentModules.push(childItem.parentId);
            } else if (changeValue.length === 0) {
                selectParentModules = selectParentModules.filter(i => i !== childItem.parentId);
            }

            // 当前选中的所有的children
            const currentChildren = childModules.filter(item => item.parentId === childItem.parentId);
            if (changeValue.length === 0 || changeValue.length === currentChildren.length) {
                // 全选 / 没有选
                indeterminateParent[childItem.parentId] = false;
            } else {
                indeterminateParent[childItem.parentId] = true;
            }

            // 取消自己的半选状态
            indeterminateChild[childId] = false;
            this.indeterminateChild = indeterminateChild;
            // parent半选中状态
            this.indeterminateParent = indeterminateParent;

            const {all, indeterminateAllElection} = this.caclAllElection({
                functionMap,
                selectedFunctionMap,
                childModules,
                selectChildModuleMap
            });
            this.indeterminateAllElection = indeterminateAllElection;

            // 表单
            this.regoinForm = {
                ...regoinForm,
                all,
                selectParentModules,
                selectedFunctionMap
            };
        },
        handleFunctionChange(childId, changeValue) {
            // 1. 只选择了一个功能，那么需要，选中child模块，parent模块
            // 2. 如果选中的模块跟所有的模块的length一致，则全选child模块，否则半选中或者不选中
            const regoinForm = this.regoinForm; // form
            const childModules = this.childModules;
            const functionMap = this.functionMap;
            const indeterminateParent = {...this.indeterminateParent}; // 选中 / 半选中
            const indeterminateChild = {...this.indeterminateChild}; // 选中 / 半选中
            let selectChildModuleMap = {...regoinForm.selectChildModuleMap};
            let selectParentModules = [...regoinForm.selectParentModules];
            const selectedFunctionMap = {...regoinForm.selectedFunctionMap};

            // 当前选中的children项
            const childItem = childModules.find(item => item.id === childId);

            // S 对 child module 是否选中操作
            if (changeValue.length > 0 && !selectChildModuleMap[childItem.parentId].includes(childId)) {
                selectChildModuleMap[childItem.parentId].push(childId);
            } else if (changeValue.length === 0) {
                selectChildModuleMap[childItem.parentId] = selectChildModuleMap[childItem.parentId].filter(
                    i => i !== childId
                );
            }
            // E 对 child module 是否选中操作

            // S 如果child module === 0 || child module length === 全选 length
            // 那么 取消parent module indeter
            // else 添加 parent module indeter
            const currentChildren = childModules.filter(item => item.parentId === childItem.parentId);
            if (
                selectChildModuleMap[childItem.parentId].length === 0 || // eslint-disable-line
                selectChildModuleMap[childItem.parentId].length === currentChildren.length
            ) {
                indeterminateParent[childItem.parentId] = false;
            } else {
                indeterminateParent[childItem.parentId] = true;
            }
            // E

            // S 如果child module > 0 && parent module 不存在
            // 那么 child module push parent module
            // else if child module > 0  then filter parent module
            if (
                selectChildModuleMap[childItem.parentId].length > 0 && // eslint-disable-line
                !selectParentModules.includes(childItem.parentId)
            ) {
                selectParentModules.push(childItem.parentId);
            } else if (selectChildModuleMap[childItem.parentId].length === 0) {
                selectParentModules = selectParentModules.filter(i => i !== childItem.parentId);
            }
            // E

            if (changeValue.length === 0 || changeValue.length === functionMap[childId].length) {
                // 选中了所有 / 或者没有选
                indeterminateChild[childId] = false;
            } else {
                indeterminateChild[childId] = true;
            }
            this.indeterminateChild = indeterminateChild;
            this.indeterminateParent = indeterminateParent;

            const {all, indeterminateAllElection} = this.caclAllElection({
                functionMap,
                selectedFunctionMap,
                childModules,
                selectChildModuleMap
            });
            this.indeterminateAllElection = indeterminateAllElection;

            this.regoinForm = {
                ...this.regoinForm,
                all,
                selectChildModuleMap,
                selectParentModules
            };
        },
        // 点击功能 item
        handleClickFunctionItem(childId, item) {
            const functionMap = this.functionMap;
            const selectedFunctionMap = {...this.regoinForm.selectedFunctionMap};
            // 取消查看 & 编辑选中也要取消
            if (item.name === '查看' && !selectedFunctionMap[childId].includes(item.id)) {
                selectedFunctionMap[childId] = [];
            }
            // 选中编辑 & 查看也要选中
            if (item.name === '编辑' && selectedFunctionMap[childId].includes(item.id)) {
                selectedFunctionMap[childId] = functionMap[childId].map(i => i.id);
            }
            this.regoinForm = {...this.regoinForm, selectedFunctionMap};
        },
        // 表格行合并
        objectSpanMethod({row, column, rowIndex, columnIndex}) {
            if (columnIndex === 0) {
                if (row.isRowSpan) {
                    return {
                        rowspan: row.rowNumber,
                        colspan: 1
                    };
                } else {
                    return {
                        rowspan: 0,
                        colspan: 0
                    };
                }
            }
            if (row.isColSpan) {
                if (columnIndex === 1) {
                    return [1, 2];
                } else if (columnIndex === 2) {
                    return [0, 0];
                }
            }
        }
    }
};
</script>